package parser

import (
	"fmt"
	"strconv"
	"strings"
)

// Token 表示词法单元
type Token struct {
	Type  TokenType
	Value string
	Pos   int // 在输入中的位置
}

// TokenType 表示token类型
// 注意：TokenType常量定义在parser_generated.go中
type TokenType int

const (
	// 特殊token（不在yacc中定义）
	TOK_EOF TokenType = 1 // EOF
	TOK_ILLEGAL TokenType = 2 // 非法token
	// 从parser_generated.go引用的常量
	TOK_IDENT_VALUE = 57346
)

// 关键字映射
var keywords = map[string]int{
	"SELECT":     57373, // TOK_SELECT
	"FROM":       57374, // TOK_FROM
	"WHERE":      57375, // TOK_WHERE
	"INSERT":     57376, // TOK_INSERT
	"INTO":       57377, // TOK_INTO
	"VALUES":     57378, // TOK_VALUES
	"UPDATE":     57379, // TOK_UPDATE
	"SET":        57380, // TOK_SET
	"DELETE":     57381, // TOK_DELETE
	"JOIN":       57382, // TOK_JOIN
	"INNER":      57383, // TOK_INNER
	"LEFT":       57384, // TOK_LEFT
	"RIGHT":      57385, // TOK_RIGHT
	"FULL":       57386, // TOK_FULL
	"CROSS":      57387, // TOK_CROSS
	"ON":         57388, // TOK_ON
	"AS":         57389, // TOK_AS
	"AND":        57390, // TOK_AND
	"OR":         57391, // TOK_OR
	"NOT":        57392, // TOK_NOT
	"IN":         57393, // TOK_IN
	"LIKE":       57394, // TOK_LIKE
	"ILIKE":      57395, // TOK_ILIKE
	"BETWEEN":    57396, // TOK_BETWEEN
	"IS":         57397, // TOK_IS
	"NULL":       57398, // TOK_NULL
	"TRUE":       57399, // TOK_TRUE
	"FALSE":      57400, // TOK_FALSE
	"DISTINCT":   57401, // TOK_DISTINCT
	"ALL":        57402, // TOK_ALL
	"ANY":        57403, // TOK_ANY
	"SOME":       57404, // TOK_SOME
	"EXISTS":     57405, // TOK_EXISTS
	"CASE":       57406, // TOK_CASE
	"WHEN":       57407, // TOK_WHEN
	"THEN":       57408, // TOK_THEN
	"ELSE":       57409, // TOK_ELSE
	"END":        57410, // TOK_END
	"GROUP":      57411, // TOK_GROUP
	"BY":         57412, // TOK_BY
	"HAVING":     57413, // TOK_HAVING
	"ORDER":      57414, // TOK_ORDER
	"ASC":        57415, // TOK_ASC
	"DESC":       57416, // TOK_DESC
	"LIMIT":      57417, // TOK_LIMIT
	"OFFSET":     57418, // TOK_OFFSET
	"UNION":      57419, // TOK_UNION
	"INTERSECT":  57420, // TOK_INTERSECT
	"EXCEPT":     57421, // TOK_EXCEPT
	"WITH":       57422, // TOK_WITH
	"OVER":       57423, // TOK_OVER
	"PARTITION":  57424, // TOK_PARTITION
	"ROWS":       57425, // TOK_ROWS
	"RANGE":      57426, // TOK_RANGE
	"UNBOUNDED":  57427, // TOK_UNBOUNDED
	"PRECEDING":  57428, // TOK_PRECEDING
	"FOLLOWING":  57429, // TOK_FOLLOWING
	"CURRENT":    57430, // TOK_CURRENT
	"ROW":        57431, // TOK_ROW
	"FIRST":      57432, // TOK_FIRST
	"LAST":       57433, // TOK_LAST
	"NULLS":      57434, // TOK_NULLS
	"CREATE":     57435, // TOK_CREATE
	"TABLE":      57436, // TOK_TABLE
	"PRIMARY":    57437, // TOK_PRIMARY
	"KEY":        57438, // TOK_KEY
	"UNIQUE":     57439, // TOK_UNIQUE
	"FOREIGN":    57440, // TOK_FOREIGN
	"REFERENCES": 57441, // TOK_REFERENCES
	"CHECK":      57442, // TOK_CHECK
	"DEFAULT":    57443, // TOK_DEFAULT
	"CONSTRAINT": 57444, // TOK_CONSTRAINT
	"INTEGER":    57348, // TOK_INTEGER
	"VARCHAR":    57445, // TOK_VARCHAR
	"DECIMAL":    57446, // TOK_DECIMAL
	"BOOLEAN":    57447, // TOK_BOOLEAN
	"TEXT":       57448, // TOK_TEXT
	"TIMESTAMP":  57449, // TOK_TIMESTAMP
	"DATE":       57450, // TOK_DATE
	"TIME":       57451, // TOK_TIME
}

// Lexer 词法分析器
type Lexer struct {
	input        string
	position     int  // 当前位置
	readPosition int  // 当前读取位置
	ch           byte // 当前字符
	result       Statement // 解析结果
}

// NewLexer 创建新的词法分析器
func NewLexer(input string) *Lexer {
	l := &Lexer{input: input}
	l.readChar()
	return l
}

// readChar 读取下一个字符
func (l *Lexer) readChar() {
	if l.readPosition >= len(l.input) {
		l.ch = 0 // ASCII NUL字符表示EOF
	} else {
		l.ch = l.input[l.readPosition]
	}
	l.position = l.readPosition
	l.readPosition++
}

// peekChar 查看下一个字符但不移动位置
func (l *Lexer) peekChar() byte {
	if l.readPosition >= len(l.input) {
		return 0
	}
	return l.input[l.readPosition]
}

// skipWhitespace 跳过空白字符
func (l *Lexer) skipWhitespace() {
	for l.ch == ' ' || l.ch == '\t' || l.ch == '\n' || l.ch == '\r' {
		l.readChar()
	}
}

// skipComment 跳过注释
func (l *Lexer) skipComment() {
	if l.ch == '-' && l.peekChar() == '-' {
		// 单行注释
		for l.ch != '\n' && l.ch != 0 {
			l.readChar()
		}
	} else if l.ch == '/' && l.peekChar() == '*' {
		// 多行注释
		l.readChar() // 跳过 '/'
		l.readChar() // 跳过 '*'
		for {
			if l.ch == '*' && l.peekChar() == '/' {
				l.readChar() // 跳过 '*'
				l.readChar() // 跳过 '/'
				break
			}
			if l.ch == 0 {
				break
			}
			l.readChar()
		}
	}
}

// readIdentifier 读取标识符
func (l *Lexer) readIdentifier() string {
	position := l.position
	for isLetter(l.ch) || isDigit(l.ch) {
		l.readChar()
	}
	return l.input[position:l.position]
}

// readNumber 读取数字
func (l *Lexer) readNumber() (string, TokenType) {
	position := l.position
	tokenType := TokenType(57348) // TOK_INTEGER

	for isDigit(l.ch) {
		l.readChar()
	}

	// 检查小数点
	if l.ch == '.' && isDigit(l.peekChar()) {
		tokenType = TokenType(57349) // TOK_FLOAT
		l.readChar() // 跳过 '.'
		for isDigit(l.ch) {
			l.readChar()
		}
	}

	// 检查科学计数法
	if l.ch == 'e' || l.ch == 'E' {
		tokenType = TokenType(57349) // TOK_FLOAT
		l.readChar()
		if l.ch == '+' || l.ch == '-' {
			l.readChar()
		}
		for isDigit(l.ch) {
			l.readChar()
		}
	}

	return l.input[position:l.position], tokenType
}

// readString 读取字符串字面量，支持完整的PostgreSQL转义序列
func (l *Lexer) readString() string {
	var result strings.Builder
	
	for {
		l.readChar()
		if l.ch == '\'' {
			// 检查是否是双引号转义 ''
			if l.peekChar() == '\'' {
				result.WriteByte('\'')
				l.readChar() // 跳过第二个引号
			} else {
				break // 字符串结束
			}
		} else if l.ch == 0 {
			break // 意外的字符串结束
		} else if l.ch == '\\' {
			// 处理转义序列
			nextCh := l.peekChar()
			switch nextCh {
			case 'n':
				result.WriteByte('\n')
				l.readChar()
			case 't':
				result.WriteByte('\t')
				l.readChar()
			case 'r':
				result.WriteByte('\r')
				l.readChar()
			case 'b':
				result.WriteByte('\b')
				l.readChar()
			case 'f':
				result.WriteByte('\f')
				l.readChar()
			case '\\':
				result.WriteByte('\\')
				l.readChar()
			case '\'':
				result.WriteByte('\'')
				l.readChar()
			case '0', '1', '2', '3', '4', '5', '6', '7':
				// 八进制转义序列 \nnn
				octal := int(nextCh - '0')
				l.readChar()
				if l.peekChar() >= '0' && l.peekChar() <= '7' {
					l.readChar()
					octal = octal*8 + int(l.ch-'0')
					if l.peekChar() >= '0' && l.peekChar() <= '7' {
						l.readChar()
						octal = octal*8 + int(l.ch-'0')
					}
				}
				result.WriteByte(byte(octal))
			case 'x':
				// 十六进制转义序列 \xHH
				l.readChar() // 跳过 'x'
				hex := 0
				for i := 0; i < 2; i++ {
					l.readChar()
					if l.ch >= '0' && l.ch <= '9' {
						hex = hex*16 + int(l.ch-'0')
					} else if l.ch >= 'a' && l.ch <= 'f' {
						hex = hex*16 + int(l.ch-'a'+10)
					} else if l.ch >= 'A' && l.ch <= 'F' {
						hex = hex*16 + int(l.ch-'A'+10)
					} else {
						break
					}
				}
				result.WriteByte(byte(hex))
			default:
				// 未知转义序列，保持原样
				result.WriteByte('\\')
				result.WriteByte(nextCh)
				l.readChar()
			}
		} else {
			result.WriteByte(l.ch)
		}
	}
	
	return result.String()
}

// readQuotedIdentifier 读取双引号标识符，支持PostgreSQL转义规则
func (l *Lexer) readQuotedIdentifier() string {
	var result strings.Builder
	
	for {
		l.readChar()
		if l.ch == '"' {
			// 检查是否是双引号转义 ""
			if l.peekChar() == '"' {
				result.WriteByte('"')
				l.readChar() // 跳过第二个引号
			} else {
				break // 标识符结束
			}
		} else if l.ch == 0 {
			break // 意外的标识符结束
		} else {
			result.WriteByte(l.ch)
		}
	}
	
	return result.String()
}

// NextToken 获取下一个token
func (l *Lexer) NextToken() Token {
	var tok Token

	l.skipWhitespace()

	// 跳过注释
	for (l.ch == '-' && l.peekChar() == '-') || (l.ch == '/' && l.peekChar() == '*') {
		l.skipComment()
		l.skipWhitespace()
	}

	switch l.ch {
	case '=':
		tok = Token{Type: TOK_EQ, Value: string(l.ch), Pos: l.position}
	case '!':
		if l.peekChar() == '=' {
			ch := l.ch
			l.readChar()
			tok = Token{Type: TOK_NE, Value: string(ch) + string(l.ch), Pos: l.position - 1}
		} else if l.peekChar() == '~' {
			// !~ 不匹配正则表达式
			ch := l.ch
			l.readChar()
			if l.peekChar() == '*' {
				// !~* 不匹配正则表达式（忽略大小写）
				l.readChar()
				tok = Token{Type: TOK_NOT_IREGEX, Value: "!~*", Pos: l.position - 2}
			} else {
				tok = Token{Type: TOK_NOT_REGEX, Value: string(ch) + string(l.ch), Pos: l.position - 1}
			}
		} else {
			tok = Token{Type: TOK_ILLEGAL, Value: string(l.ch), Pos: l.position}
		}
	case '<':
		if l.peekChar() == '=' {
			ch := l.ch
			l.readChar()
			tok = Token{Type: TOK_LE, Value: string(ch) + string(l.ch), Pos: l.position - 1}
		} else if l.peekChar() == '>' {
			ch := l.ch
			l.readChar()
			tok = Token{Type: TOK_NE, Value: string(ch) + string(l.ch), Pos: l.position - 1}
		} else if l.peekChar() == '<' {
			// << 左移位运算符
			ch := l.ch
			l.readChar()
			tok = Token{Type: TOK_LSHIFT, Value: string(ch) + string(l.ch), Pos: l.position - 1}
		} else {
			tok = Token{Type: TOK_LT, Value: string(l.ch), Pos: l.position}
		}
	case '>':
		if l.peekChar() == '=' {
			ch := l.ch
			l.readChar()
			tok = Token{Type: TOK_GE, Value: string(ch) + string(l.ch), Pos: l.position - 1}
		} else if l.peekChar() == '>' {
			// >> 右移位运算符
			ch := l.ch
			l.readChar()
			tok = Token{Type: TOK_RSHIFT, Value: string(ch) + string(l.ch), Pos: l.position - 1}
		} else {
			tok = Token{Type: TOK_GT, Value: string(l.ch), Pos: l.position}
		}
	case '+':
		tok = Token{Type: TOK_PLUS, Value: string(l.ch), Pos: l.position}
	case '-':
		tok = Token{Type: TOK_MINUS, Value: string(l.ch), Pos: l.position}
	case '*':
		tok = Token{Type: TOK_MULTIPLY, Value: string(l.ch), Pos: l.position}
	case '/':
		tok = Token{Type: TOK_DIVIDE, Value: string(l.ch), Pos: l.position}
	case '%':
		tok = Token{Type: TOK_MODULO, Value: string(l.ch), Pos: l.position}
	case '|':
		if l.peekChar() == '|' {
			ch := l.ch
			l.readChar()
			tok = Token{Type: TOK_CONCAT, Value: string(ch) + string(l.ch), Pos: l.position - 1}
		} else {
			// 单个 | 可能用于位运算或其他操作
			tok = Token{Type: TOK_ILLEGAL, Value: string(l.ch), Pos: l.position}
		}
	case '~':
		if l.peekChar() == '*' {
			// ~* 匹配正则表达式（忽略大小写）
			ch := l.ch
			l.readChar()
			tok = Token{Type: TOK_IREGEX, Value: string(ch) + string(l.ch), Pos: l.position - 1}
		} else {
			// ~ 匹配正则表达式
			tok = Token{Type: TOK_REGEX, Value: string(l.ch), Pos: l.position}
		}
	case '^':
		if l.peekChar() == '@' {
			// ^@ 前缀匹配运算符
			ch := l.ch
			l.readChar()
			tok = Token{Type: TOK_ILLEGAL, Value: string(ch) + string(l.ch), Pos: l.position - 1} // 暂时标记为ILLEGAL，需要在parser.y中定义
		} else {
			// ^ 异或运算符
			tok = Token{Type: TOK_ILLEGAL, Value: string(l.ch), Pos: l.position} // 暂时标记为ILLEGAL
		}
	case '&':
		// & 位与运算符
		tok = Token{Type: TOK_ILLEGAL, Value: string(l.ch), Pos: l.position} // 暂时标记为ILLEGAL
	case '#':
		// # 异或运算符（PostgreSQL特有）
		tok = Token{Type: TOK_ILLEGAL, Value: string(l.ch), Pos: l.position} // 暂时标记为ILLEGAL
	case ',':
		tok = Token{Type: TokenType(57368), Value: string(l.ch), Pos: l.position} // TOK_COMMA
	case ';':
		tok = Token{Type: TokenType(57369), Value: string(l.ch), Pos: l.position} // TOK_SEMICOLON
	case '(':
		tok = Token{Type: TokenType(57370), Value: string(l.ch), Pos: l.position} // TOK_LPAREN
	case ')':
		tok = Token{Type: TokenType(57371), Value: string(l.ch), Pos: l.position} // TOK_RPAREN
	case '.':
		tok = Token{Type: TokenType(57372), Value: string(l.ch), Pos: l.position} // TOK_DOT
	case '\'':
		tok.Type = TokenType(57347) // TOK_STRING
		tok.Value = l.readString()
		tok.Pos = l.position
	case '"':
		tok.Type = TOK_IDENT
		tok.Value = l.readQuotedIdentifier()
		tok.Pos = l.position
	case 0:
		tok = Token{Type: TOK_EOF, Value: "", Pos: l.position}
	default:
		if isLetter(l.ch) {
			tok.Value = l.readIdentifier()
			tok.Type = lookupIdent(tok.Value)
			tok.Pos = l.position
			return tok
		} else if isDigit(l.ch) {
			tok.Value, tok.Type = l.readNumber()
			tok.Pos = l.position
			return tok
		} else {
			tok = Token{Type: TOK_ILLEGAL, Value: string(l.ch), Pos: l.position}
		}
	}

	l.readChar()
	return tok
}

// lookupIdent 查找标识符类型
func lookupIdent(ident string) TokenType {
	if tokenType, ok := keywords[strings.ToUpper(ident)]; ok {
		return TokenType(tokenType)
	}
	return TokenType(TOK_IDENT_VALUE)
}

// isLetter 检查是否为字母
func isLetter(ch byte) bool {
	return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_'
}

// isDigit 检查是否为数字
func isDigit(ch byte) bool {
	return '0' <= ch && ch <= '9'
}

// TokenString 返回token类型的字符串表示
func (t TokenType) String() string {
	switch t {
	case TOK_EOF:
		return "EOF"
	case TOK_ILLEGAL:
		return "ILLEGAL"
	case 57346: // TOK_IDENT
		return "IDENT"
	case 57347: // TOK_STRING
		return "STRING"
	case 57348: // TOK_INTEGER
		return "INTEGER"
	case 57349: // TOK_FLOAT
		return "FLOAT"
	case 57350: // TOK_EQ
		return "="
	case 57351: // TOK_NE
		return "<>"
	case 57352: // TOK_LT
		return "<"
	case 57353: // TOK_LE
		return "<="
	case 57354: // TOK_GT
		return ">"
	case 57355: // TOK_GE
		return ">="
	case 57356: // TOK_PLUS
		return "+"
	case 57357: // TOK_MINUS
		return "-"
	case 57358: // TOK_MULTIPLY
		return "*"
	case 57359: // TOK_DIVIDE
		return "/"
	case 57360: // TOK_MODULO
		return "%"
	case 57361: // TOK_CONCAT
		return "||"
	case 57362: // TOK_COMMA
		return ","
	case 57363: // TOK_SEMICOLON
		return ";"
	case 57364: // TOK_LPAREN
		return "("
	case 57365: // TOK_RPAREN
		return ")"
	case 57366: // TOK_DOT
		return "."
	case 57367: // TOK_SELECT
		return "SELECT"
	case 57368: // TOK_FROM
		return "FROM"
	case 57369: // TOK_WHERE
		return "WHERE"
	// 添加更多关键字...
	default:
		return fmt.Sprintf("TokenType(%d)", int(t))
	}
}

// String 返回Token的字符串表示
func (t Token) String() string {
	return fmt.Sprintf("Token{Type: %s, Value: %s, Pos: %d}", t.Type, t.Value, t.Pos)
}

// Lex 实现 yyLexer 接口的 Lex 方法
func (l *Lexer) Lex(lval *yySymType) int {
	tok := l.NextToken()
	
	switch tok.Type {
	case TOK_EOF:
		return 0
	case TOK_IDENT:
		lval.str = tok.Value
		return TOK_IDENT
	case TOK_STRING:
		lval.str = tok.Value
		return TOK_STRING
	case TOK_INTEGER:
		if val, err := strconv.ParseInt(tok.Value, 10, 64); err == nil {
			lval.intVal = val
		} else {
			lval.intVal = 0
		}
		return TOK_INTEGER
	case TOK_FLOAT:
		if val, err := strconv.ParseFloat(tok.Value, 64); err == nil {
			lval.floatVal = val
		} else {
			lval.floatVal = 0.0
		}
		return TOK_FLOAT
	default:
		return int(tok.Type)
	}
}

// Error 实现 yyLexer 接口的 Error 方法
func (l *Lexer) Error(s string) {
	fmt.Printf("Parse error at position %d: %s\n", l.position, s)
}

// Parse 解析SQL语句并返回AST
func Parse(input string) (Statement, error) {
	lexer := NewLexer(input)
	parser := yyNewParser()
	result := parser.Parse(lexer)
	if result != 0 {
		return nil, fmt.Errorf("parse failed")
	}
	return lexer.result, nil
}